#pragma once

#include "oper.h"

#define NUM_NUMS 4
#define OPERATOR_NUMS (NUM_NUMS - 1)

typedef struct {
	u8_s left_index;
	u8_s right_index;
} tree_link_t;

typedef struct {
	tree_link_t link_a[OPERATOR_NUMS];
} tree_struct_t;

// 固定结构体
typedef struct {
	__attribute__((packed)) oper_e oper : 8;
} pack_oper_s;

// 固定结构体
typedef struct {
	i8_s num_a[NUM_NUMS];
} num_group_s;

// 对外提供：tree34_t
typedef struct {
	const tree_struct_t* struct_p;
	pack_oper_s oper_a[OPERATOR_NUMS];
	num_group_s num_group;
} tree34_t;

// 对外提供：node_t
typedef u8_s node_t;

// 固定结构体
typedef struct {
	const node_t* left_p;
	const node_t* right_p;
} sub_nodes_t;

// 对外提供：node_get_head()
static inline const node_t* tree_get_head(const tree34_t* tree_p) {
	static const u8_s head_index = 0;
	return &head_index;
}

// 对外提供：node_get_sub()
static inline sub_nodes_t node_get_sub(const tree34_t* tree_p,
				       const node_t* node_p) {
	u32_s node_no = *node_p;
	const tree_link_t* link_p = &(tree_p->struct_p->link_a[node_no]);
	sub_nodes_t sub_nodes = {
		.left_p = &(link_p->left_index),
		.right_p = &(link_p->right_index),
	};
	return sub_nodes;
}

// 对外提供：node_is_oper()
static inline b32_s node_is_oper(const tree34_t* tree_p, const node_t* node_p) {
	u32_s node_no = *node_p;
	return (node_no < OPERATOR_NUMS);
}

// 对外提供：node_get_oper()
static inline oper_e node_get_oper(const tree34_t* tree_p,
				   const node_t* node_p) {
	u32_s node_no = *node_p;
	return tree_p->oper_a[node_no].oper;
}

// 对外提供：node_get_num()
static inline i32_s node_get_num(const tree34_t* tree_p, const node_t* node_p) {
	u32_s node_no = *node_p;
	u32_s num_no = node_no - OPERATOR_NUMS;
	return tree_p->num_group.num_a[num_no];
}

// 对外提供：tree_set_oper()
static inline void tree_set_oper(tree34_t* tree_p, u32_s oper_no, oper_e oper) {
	tree_p->oper_a[oper_no].oper = oper;
}

// 对外提供：tree_set_num()
static inline void tree_set_num(tree34_t* tree_p, u32_s num_no, i32_s num) {
	tree_p->num_group.num_a[num_no] = num;
}
